iT邦幫忙

2024 iThome 鐵人賽

DAY 26
0
Modern Web

剛入行就一人重新打造公司前端系統?系列 第 26

Day 26 - useState 的異步更新問題

  • 分享至 

  • xImage
  •  

寫 React 時,新手很容易遇到 useState 異步更新的問題。查找資料時,我發現有人在 reddit 發了一篇文章,表示自己是 React 新手,還因為怕問題太基本或愚蠢而道歉。底下有個很棒的回覆:「這問題雖然基本,但一點都不愚蠢。我敢打賭幾乎每個人都至少犯過一次這個錯誤,所以不用擔心。」這讓我覺得,學習中不要害怕提出問題,重點是透過問題不斷學習和成長。

操作 useState 時發生「慢一步」更新的問題,應該也是初學時容易搞不懂的部分。原因在於當你使用 setState 更新狀態時,React 並不會立即更新,而是將其標記為「需要更新」,並在下一次渲染時才真正更新狀態值。這就是 狀態更新是異步的,因此你在調用 setState 後,如果馬上嘗試獲取新狀態,可能還會得到舊的值。

useState 的異步更新問題

  • 使用 useState 時,資料更新往往慢一步,這是因為狀態更新是異步進行的:
const [count, setCount] = useState(0);

const handleIncrement = () => {
  setCount(count + 1);
  console.log(count); // 可能會預期這裡會顯示更新後的 count,但實際上是舊的值
};

如果希望能夠即時取得更新後的狀態值,該怎麼處理呢?

解決方式:使用 useEffect 來追蹤狀態變化

const [count, setCount] = useState(0);

useEffect(() => {
  console.log(count); // 當 count 改變時,這裡會顯示最新的值
}, [count]);

const handleIncrement = () => {
  setCount(count + 1);
};

為什麼 useState 要設計成異步的?

React 之所以選擇異步更新,是為了提升效能。當多次調用 setState 時,React 會將多次更新合併起來,並且在合適的時機一起更新 DOM,避免頻繁的 DOM 操作,從而提高渲染效能。

// 多次 setState 的範例

function App() {
  const [count, setCount] = useState(0);

  const incrementTwice = () => {
    setCount(prevCount => prevCount + 1);
    setCount(prevCount => prevCount + 1); // 確保每次更新都基於最新的狀態值
  };

  return (
    <button onClick={incrementTwice}>增加兩次</button>
  );
}

參考資料


上一篇
Day 25 - 寫 React 為何會觸發瘋狂的重新渲染?
下一篇
Day 27 - 儲存可變資料而不觸發重新渲染的 useRef
系列文
剛入行就一人重新打造公司前端系統?27
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言